﻿using System;
using System.Windows;
using AllenalaMente.MogadeCode;
using Mogade;
using AllenalaMente.State;
using System.Windows.Threading;

namespace AllenalaMente.Pages
{
    public partial class LeaderboardPage
    {
        private static readonly LeaderboardScope[] _scopeOrder = new[] { LeaderboardScope.Overall, LeaderboardScope.Weekly, LeaderboardScope.Daily };
        private LeaderboardScope _scope;
        private int _page;
        private DispatcherTimer updateTimer;

        GameState gameState = GameStateManager.GetState();

        //private int _level = 1000;
        private int _score;

        public LeaderboardPage()
        {
            InitializeComponent();

            ApplicationTitle.Text = Locale.Strings.Leaderboard;
            textboxPoints.Text = Locale.Strings.LeaderboardText;

            if (gameState.BestScore == gameState.lastPubishedScore)
            {
                if (gameState.lastPubishedScore != 0)
                    textboxPoints.Text = Locale.Strings.AlreadyScorePublished;
                else
                    textboxPoints.Text = Locale.Strings.NoScoreToPublish;

                Submit.Opacity = 0.3;
                bestScoreBox.Text = gameState.lastPubishedScore.ToString() + "!";
                Submit.Click -= Submit_Click;
            }
            else
            {
                Submit.Opacity = 1;
                Submit.Click += Submit_Click;
                textboxPoints.Text = Locale.Strings.LeaderboardText;
                bestScoreBox.Text = gameState.BestScore.ToString() + "!";
            }

            bestScoreText.Text = Locale.Strings.BestScore;
            Submit.Content = Locale.Strings.Submit;
            TitleUserName.Text = Locale.Strings.Username;
            TitleScore.Text = Locale.Strings.Score;


            //_level = 1;
            _score = gameState.BestScore;

            // Update timer reload Leaderboard
            updateTimer = new DispatcherTimer();
            updateTimer.Interval = TimeSpan.FromMilliseconds(5);
            updateTimer.Tick += new EventHandler(updateTimer_Tick);
       

        }

        double realoadLeaderboardTimer = 100;
        void updateTimer_Tick(object sender, EventArgs e)
        {
            realoadLeaderboardTimer -= updateTimer.Interval.Milliseconds;
            if (realoadLeaderboardTimer < 0)
            {
                realoadLeaderboardTimer = 100;
                LoadLeaderboard();
                updateTimer.Stop();
            
            }
        }

        protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
        {
            _scope = _scopeOrder[0];
            _page = 1;
            LoadLeaderboard();
            base.OnNavigatedTo(e);
        }

        private void NextScope_Click(object sender, RoutedEventArgs e)
        {
            var index = Array.IndexOf(_scopeOrder, _scope);
            if (++index == _scopeOrder.Length)
            {
                index = 0;
            }
            _scope = _scopeOrder[index];
            LoadLeaderboard();
        }

        private void PreviousScope_Click(object sender, RoutedEventArgs e)
        {
            var index = Array.IndexOf(_scopeOrder, _scope);
            if (--index == -1)
            {
                index = _scopeOrder.Length - 1;
            }
            _scope = _scopeOrder[index];
            LoadLeaderboard();
        }

        private void LoadLeaderboard()
        {

            // Orrificio per eludere la enum in inglese da cui prende i valori castandoli a string
            if (Submit.Content.ToString() == "pubblica") // vedo se la lingue è italiana
                switch (_scope)
                {
                    case LeaderboardScope.Daily:
                        ScopeTitle.Text = "Giornaliera";
                        break;
                    case LeaderboardScope.Overall:
                        ScopeTitle.Text = "Generale";
                        break;
                    case LeaderboardScope.Weekly:
                        ScopeTitle.Text = "Settimanale";
                        break;
                    case LeaderboardScope.Yesterday:
                        ScopeTitle.Text = "Ieri";
                        break;
                    default:
                        break;
                }
            else
                ScopeTitle.Text = _scope.ToString();

            //we can avoid the cross-thread issue by dispatching the entire callback, but don't do too much!
            Mogade.GetLeaderboard(MogadeHelper.LeaderboardId(Leaderboards.Main), _scope, _page, r => Dispatcher.BeginInvoke(() => LeaderboardReceived(r)));
            //could put a loading message here
        }

        private void LeaderboardReceived(Response<LeaderboardScores> response)
        {
            //would hide the loading message here
            if (!response.Success)
            {
                //todo handle the error, maybe display a message to the user
            }
            else
            {
                Scores.Children.Clear();
                for (var i = 0; i < response.Data.Scores.Count; ++i)
                {
                    var row = new ScoreRow(response.Data.Scores[i]);
                    Scores.Children.Add(row);
                }
            }
        }

        public void Submit_Click(object sender, RoutedEventArgs e)
        {
            //if ( gameState.BestScore == 0 )
            //{
            //    textboxPoints.Text = Locale.Strings.NoScoreToPublish;
            //    textboxPoints.FontSize = 16;

            //    return;
            //}
            gameState.lastPubishedScore = gameState.BestScore;
            Submit.IsEnabled = false;
            Submit.Content = Locale.Strings.SubmitSending;

            //we can store a bit of arbitrary data in the Data field which we can then use in our leaderboard
            //you can always not set the Data if you have no extra information you want to store with the score
            //var score = new Score { Data = _level.ToString(), Points = _score, UserName = gameState.playerName};
            var score = new Score { Points = _score, UserName = gameState.playerName };
            Mogade.SaveScore(MogadeHelper.LeaderboardId(Leaderboards.Main), score, ScoreResponseHandler);

            updateTimer.Start();
        }

        private void ScoreResponseHandler(Response<SavedScore> r)
        {
            if (!r.Success)
            {
                //todo handle error
            }
            else
            {
                var text = string.Format("Daily Rank: {0}\rOverall Rank: {1}", r.Data.Ranks.Daily, r.Data.Ranks.Overall);
                if (r.Data.Highs.Overall)
                {
                    text = "Wow, that was an all-time personal best!\r" + text;
                }
                if (r.Data.Highs.Daily)
                {
                    text += "Your best score today!\r" + text;
                }

                //we are in a separate thread, we can't just update controls from the main thread.
                Dispatcher.BeginInvoke(() =>
                {
                    Submit.Visibility = Visibility.Collapsed;
                    //var block = new TextBlock { Text = text, TextAlignment = TextAlignment.Center, VerticalAlignment = VerticalAlignment.Center, FontSize = 20, Foreground = new SolidColorBrush(Colors.White) };
                    //ContentPanel.Children.Add(block);
                });
            }
        }
    }
}